package start

import (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"gitee.com/hexug/devcloud/cmdb/apps"
	"gitee.com/hexug/devcloud/cmdb/common/logger"
	"gitee.com/hexug/devcloud/cmdb/conf"
	"gitee.com/hexug/devcloud/cmdb/protocol"
	"github.com/spf13/cobra"
)

var (
	Path string
	Cmd  = &cobra.Command{
		Use:   "start",
		Short: "启动服务",
		Long:  "启动cmdb服务",

		Run: func(cmd *cobra.Command, args []string) {

			conf.LoadConfigFromToml(Path)
			fmt.Println("配置文件读取完成")
			conf.LoadConfigFromEnv()
			fmt.Println("环境变量读取完成\n注意：配置过的环境变量会覆盖配置文件参数！！！")

			//接收信号
			ch := make(chan os.Signal, 1)
			defer close(ch)
			signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGQUIT)

			//初始化app
			apps.InitApp()

			// 初始化服务
			svr, err := newService()
			if err != nil {
				panic(err)
			}

			//监听信号
			go svr.waitSign(ch)

			//启服务
			if err := svr.start(); err != nil {
				if !strings.Contains(err.Error(), "http: Server closed") {
					panic(err)
				}
			}
		},
	}
)

func init() {
	Cmd.Flags().StringVarP(&Path, "path", "f", "etc/config.toml", "配置文件信息")
}

type service struct {
	http *protocol.HTTPService
	grpc *protocol.GRPCService
}

func newService() (*service, error) {
	grpc := protocol.NewGRPCService()
	http := protocol.NewHTTPService()
	svr := &service{
		http: http,
		grpc: grpc,
	}

	return svr, nil
}

// 当接收到信号
func (s *service) waitSign(sign chan os.Signal) {
	//遍历管道
	for sg := range sign {
		//查看类型
		switch v := sg.(type) {
		//符合上面定义的管道的信号就会进来
		default:
			logger.L().Infof("接收到的信号： %v, 开始优雅的关闭服务", v.String())
			//先关闭grpc
			if err := s.grpc.Stop(); err != nil {
				logger.L().Infof("grpc服务优雅的关闭失败: %s, 强制退出", err)
			} else {
				logger.L().Info("grpc服务关闭完成")
			}
			//再关闭http服务
			if err := s.http.Stop(); err != nil {
				logger.L().Infof("http服务优雅的关闭失败: %s, force exit", err)
			} else {
				logger.L().Info("http服务关闭完成")
			}
			return
		}
	}
}

func (s *service) start() error {
	logger.L().Infof("注册过的grpc: %s", apps.InitedGrpc())
	logger.L().Infof("注册过的http api: %s", apps.InitedHttp())

	logger.L().Infof("注册过的app: %s", apps.InitedApp())

	go s.grpc.Start()
	return s.http.Start()
}
